<!--
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-03-14 14:06:26
 * @Description  : 用户设置-账户
-->
<template>
  <div class="flex items-center">
    <left-line class="w-0"></left-line>
    个人账号
  </div>
  <n-divider class="!my-2" />

  <!-- 头像修改 -->
  <div class="avator item">
    <div class="title">
      <SvgIcon icon="tupian1" class="mr-1"></SvgIcon>
      个人头像
    </div>
    <div class="info">
      <n-upload
        :custom-request="customRequest"
        accept="image/*"
        @before-upload="beforeUpload"
        :show-file-list="false"
      >
        <n-avatar
          class="cursor-pointer"
          round
          :size="48"
          :src="renderAvatorSrc(userStore.userInfo?.avator as string)"
        />
      </n-upload>
    </div>
    <div class="action">
      <n-button text type="primary">编辑</n-button>
    </div>
  </div>
  <n-divider class="!my-2" />

  <!-- 昵称修改 -->
  <div class="nickname item">
    <div class="title">
      <SvgIcon icon="yonghu1" size="18px" class="mr-1"></SvgIcon>
      个人昵称
    </div>
    <div class="info">
      <n-form
        :rules="formRules"
        v-if="editModel.nickname"
        ref="nickNameformRef"
        :label-width="0"
        :label-placement="'left'"
        label-align="left"
        :model="userProfile"
        size="small"
        require-mark-placement="left"
      >
        <n-form-item label="" path="nickname">
          <n-input
            class="!w-[300px]"
            v-model:value="userProfile.nickname"
            placeholder="请输入新昵称"
            :allow-input="noSideSpace"
            clearable
          />
          <div class="ml-[12px] text-gray-400 text-[12px]">不能重复</div>
        </n-form-item>
        <div class="flex">
          <n-button size="small" type="primary" @click="handleSaveNickname">
            确定
          </n-button>
          <n-button
            class="ml-2"
            size="small"
            @click="editModel.nickname = false"
          >
            取消
          </n-button>
        </div>
      </n-form>
      <span v-else @click="editModel.nickname = true" class="cursor-pointer">
        {{ userStore.userInfo?.nickname || '暂无,点击设置昵称' }}
      </span>
    </div>
    <!-- 展示编辑表单 -->
    <div class="action">
      <n-button
        text
        type="primary"
        @click="editModel.nickname = true"
        v-if="!editModel.nickname"
      >
        编辑
      </n-button>
      <n-button circle @click="editModel.nickname = false" size="small" v-else>
        <SvgIcon icon="chacha"></SvgIcon>
      </n-button>
    </div>
  </div>
  <n-divider class="!my-2" />

  <!-- 邮箱修改 -->
  <div class="email item">
    <div class="title">
      <SvgIcon icon="youxiang" class="mr-1"></SvgIcon>
      email
    </div>
    <div class="info">
      <n-form
        :rules="formRules"
        v-if="editModel.email"
        ref="emailformRef"
        :label-width="0"
        :label-placement="'left'"
        label-align="left"
        :model="userProfile"
        size="small"
        require-mark-placement="left"
      >
        <n-form-item label="" path="email">
          <n-input
            class="!w-[300px]"
            v-model:value="userProfile.email"
            placeholder="请输入邮箱地址"
            :allow-input="noSideSpace"
            clearable
          />
          <div class="ml-[12px] text-gray-400 text-[12px]">
            部分业务需要邮箱验证
          </div>
        </n-form-item>
        <n-form-item label="" path="emailCode">
          <n-input-group>
            <n-input
              class="!w-[200px]"
              v-model:value="userProfile.emailCode"
              placeholder="请输入邮箱验证码"
              :allow-input="noSideSpace"
              clearable
            />
            <n-button
              type="primary"
              ghost
              @click="sendCodeValidate"
              v-if="emailCodeSecond === 0"
              :disabled="!canSendCode"
            >
              发送验证码
            </n-button>
            <n-button type="primary" ghost v-else>
              {{ emailCodeSecond + 's' }}
            </n-button>
          </n-input-group>
        </n-form-item>
        <div class="flex">
          <n-button size="small" type="primary" @click="handleSaveEmail">
            确定
          </n-button>
          <n-button class="ml-2" size="small" @click="handleEmailShow(false)">
            取消
          </n-button>
        </div>
      </n-form>
      <span @click="handleEmailShow(true)" v-else class="cursor-pointer">
        {{ userStore.userInfo?.email || '未绑定，点击绑定邮箱' }}
      </span>
    </div>
    <div class="action">
      <n-button
        text
        type="primary"
        @click="handleEmailShow(true)"
        v-if="!editModel.email"
      >
        编辑
      </n-button>
      <n-button circle @click="handleEmailShow(false)" size="small" v-else>
        <SvgIcon icon="chacha"></SvgIcon>
      </n-button>
    </div>
  </div>
  <n-modal v-model:show="dialogs.sendMsg">
    <PicValidCode
      @on-finish="handleFinish"
      @visible-change="handleVisibleChange"
    ></PicValidCode>
  </n-modal>
  <n-divider class="!my-2" />

  <!-- 密码 -->
  <div class="pwd item">
    <div class="title">
      <SvgIcon icon="classkaisuohuansuo" class="mr-1"></SvgIcon>
      密码
    </div>
    <div class="info">
      <n-form
        :rules="formRules"
        v-if="editModel.password"
        ref="passwordformRef"
        :label-width="0"
        :label-placement="'left'"
        label-align="left"
        :model="userProfile"
        size="small"
        require-mark-placement="left"
      >
        <n-form-item label="" path="oldPassword">
          <n-input
            class="!w-[300px]"
            v-model:value="userProfile.oldPassword"
            placeholder="请输入原密码"
            :allow-input="noSideSpace"
            clearable
            type="password"
            show-password-on="click"
          />
          <div class="ml-[12px] text-gray-400 text-[12px]">
            忘记密码？你可以进行
            <n-button text type="primary" @click="handleToResetPwd"
              >重置</n-button
            >
          </div>
        </n-form-item>
        <n-form-item label="" path="password">
          <n-input
            class="!w-[300px]"
            v-model:value="userProfile.password"
            placeholder="请输入新密码"
            :allow-input="noSideSpace"
            clearable
            type="password"
            show-password-on="click"
          />
        </n-form-item>
        <n-form-item label="" path="repassword">
          <n-input
            class="!w-[300px]"
            v-model:value="userProfile.repassword"
            placeholder="请再次输入密码"
            :allow-input="noSideSpace"
            clearable
            type="password"
            show-password-on="click"
          />
        </n-form-item>
        <div class="flex">
          <n-button size="small" type="primary" @click="handleSavePassword">
            确定
          </n-button>
          <n-button class="ml-2" size="small" @click="handlePwdShow(false)">
            取消
          </n-button>
        </div>
      </n-form>
      <span v-else class="cursor-pointer" @click="handlePwdShow(true)">
        点击修改密码
      </span>
    </div>
    <div class="action">
      <n-button
        text
        type="primary"
        @click="handlePwdShow(true)"
        v-if="!editModel.password"
      >
        编辑
      </n-button>
      <n-button circle @click="handlePwdShow(false)" size="small" v-else>
        <SvgIcon icon="chacha"></SvgIcon>
      </n-button>
    </div>
  </div>

  <n-divider class="!my-2" />
  <!-- 三方账号 -->
  <!-- <div class="flex items-center mt-10">
    <left-line class="w-0"></left-line>
    第三方账号
  </div>
  <n-divider class="!my-2" /> -->

  <!-- <div class="qq item">
    <div class="title">
      <SvgIcon icon="QQ" class="mr-1" color="#199ae3"></SvgIcon>
      QQ
    </div>
    <div class="info">点击绑定</div>
    <div class="action">
      <n-button text type="primary">编辑</n-button>
    </div>
  </div> -->
  <!-- <n-divider class="!my-2" /> -->

  <!-- <div class="pwd item">
    <div class="title">
      <SvgIcon icon="weixin" class="mr-1" color="#18a058"></SvgIcon>
      微信
    </div>
    <div class="info">点击绑定</div>
    <div class="action">
      <n-button text type="primary">编辑</n-button>
    </div>
  </div> -->
  <!-- <n-divider class="!my-2" /> -->
</template>

<script setup lang="ts">
import { useMessage } from 'naive-ui'
import type {
  UploadCustomRequestOptions,
  UploadFileInfo,
  FormInst
} from 'naive-ui'
import useUserStore from '@/stores/modules/user'
import { updateUserProfile, validateUserProfile } from '@/api/user'
import type { UserProfileReq } from '@/types/user'
import { noSideSpace } from '@/utils'
import { load } from '@/utils/loading'
import { renderAvatorSrc } from '@/utils/commonBusiness'
import { userSchema } from '@/utils/rule'
import { useSendCode } from '@/hooks/useSendCode'
const userStore = useUserStore()
const message = useMessage()

const { sendCode, emailCodeSecond } = useSendCode()
const router = useRouter()

// 是否进入编辑模式
const editModel = reactive({
  nickname: false,
  password: false,
  email: false,
  qq: false,
  weixin: false
})

const userProfile = reactive({
  nickname: '',
  oldPassword: '',
  password: '',
  repassword: '',
  email: '',
  emailCode: '',
  qq: '',
  weixin: ''
})

const formRules = {
  nickname: userSchema.nickname,
  email: [
    ...userSchema.email,
    {
      // 异步校验用户名是否被占用
      message: '邮箱被占用',
      trigger: 'blur',
      validator: (rule: any, value: string) => {
        return new Promise<void>((resolve, reject) => {
          validateUserProfile({
            email: value
          })
            .then(() => {
              resolve()
              canSendCode.value = true
            })
            .catch(() => {
              reject('邮箱被占用')
              canSendCode.value = false
            })
        })
      }
    }
  ],
  emailCode: userSchema.emailCode,
  password: userSchema.password,
  oldPassword: userSchema.password,
  repassword: [
    {
      required: true,
      message: '请再次输入密码',
      trigger: ['blur']
    },
    {
      validator: (rule: any, value: string) => {
        return value === userProfile.password
      },
      message: '两次输入密码不一致',
      trigger: ['blur']
    }
  ]
}

const canSendCode = ref(false)

const putUserProfile = (profileReq: UserProfileReq, messageRes: string) => {
  load.show()
  updateUserProfile(profileReq)
    .then(() => {
      message.success(messageRes)
      editModel[profileReq.type as keyof typeof editModel] = false
      userStore.getUserInfo()
    })
    .catch(console.error)
    .finally(() => {
      load.hide()
    })
}

const nickNameformRef = ref<FormInst | null>(null)
// 保存昵称
const handleSaveNickname = () => {
  nickNameformRef.value?.validate((error) => {
    if (error) {
      return
    }
    putUserProfile(
      { type: 'nickname', nickname: userProfile.nickname },
      '修改昵称成功'
    )
  })
}

// ========================================= 更新邮箱的相关操作 ===========================================
const emailformRef = ref<FormInst | null>()
const handleEmailShow = (value: boolean) => {
  editModel.email = value
}

const dialogs = reactive({
  sendMsg: false
})

// 发送验证码之前的图片验证码
const sendCodeValidate = () => {
  dialogs.sendMsg = true
}

const handleVisibleChange = (value: boolean) => {
  dialogs.sendMsg = value
}

const handleFinish = (picCode: string) => {
  // 进行发送验证码的操作，带上一个图片验证码值
  sendCode('bindEmail', 'email', userProfile.email, picCode)
  dialogs.sendMsg = false
}

// 保存email
const handleSaveEmail = () => {
  emailformRef.value?.validate((error) => {
    if (error) {
      return
    }
    putUserProfile(
      { type: 'email', email: userProfile.email, code: userProfile.emailCode },
      '修改邮箱成功'
    )
  })
}

onMounted(async () => {
  if (!userStore.userInfo) {
    await userStore.getUserInfo()
  }
  userProfile.email = userStore.userInfo?.email || ''
  userProfile.nickname = userStore.userInfo?.nickname || ''
})

// =================================================更新密码的相关操作=========================================
const handlePwdShow = (value: boolean) => {
  editModel.password = value
}

const passwordformRef = ref<FormInst | null>()
// 更新密码
const handleSavePassword = () => {
  passwordformRef.value?.validate((error) => {
    if (error) {
      return
    }

    putUserProfile(
      {
        type: 'password',
        oldPassword: userProfile.oldPassword,
        password: userProfile.password
      },
      '修改密码成功'
    )
  })
}

const handleToResetPwd = () => {
  router.push({
    name: 'login'
  })
}

// ================================================ 更新头像的相关操作========================================
const beforeUpload = (data: { file: UploadFileInfo }) => {
  if (!data.file.file?.type.startsWith('image')) {
    message.error('只能上传图片文件，请重新上传')
    return false
  }

  // 限制图片大小为2mb
  if (data.file.file?.size > 1024 * 1024 * 2) {
    message.error('图片大小限制为2mb，请重新上传')
    return false
  }

  return true
}

const avatorSrc = ref('')
const customRequest = ({
  file,
  data,
  headers,
  withCredentials,
  action,
  onFinish,
  onError,
  onProgress
}: UploadCustomRequestOptions) => {
  console.log(file, 'file')

  const reader = new FileReader()

  reader.readAsDataURL(file.file as Blob) // 以base64方式读取文件内容
  reader.onloadstart = function (e) {
    // 当读取操作开始时触发
    console.log('开始读取 onloadstart:', e)
  }
  reader.onabort = function (e) {
    // 当读取操作被中断时触发
    console.log('读取中止 onabort:', e)
  }
  reader.onerror = function (e) {
    // 当读取操作发生错误时触发
    console.log('读取错误 onerror:', e)
  }

  reader.onprogress = function (e) {
    // 在读取Blob时触发，读取上传进度，50ms左右调用一次
    console.log('读取中 onprogress:', e)
    console.log('已读取:', Math.ceil((e.loaded / e.total) * 100) + '%')
  }

  reader.onload = (e) => {
    // 当读取操作成功完成时调用
    console.log('读取成功 onload:', e)
    // 该文件的base64数据，前端可直接用来展示图片,若使用<img id="img">标签展示图片，可直接赋值src属性
    avatorSrc.value = e.target!.result as string
    // 调用上传接口，上传base64格式的文件数据

    // 更新头像的请求
    updateUserProfile({
      type: 'avator',
      avator: e.target!.result as string,
      avatorName: file.file!.name
    })
      .then(() => {
        message.success('更新头像成功')
        userStore.getUserInfo()
        onFinish()
      })
      .catch(() => {
        onError()
      })
      .finally(() => {})
  }
}
</script>

<style scoped lang="scss">
.item {
  color: #444;
  font-size: 13px;
  min-height: 60px;
  padding: 5px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  .title {
    flex: 3;
    display: flex;
    align-items: center;
  }

  .info {
    flex: 7;
  }

  .action {
    flex: 1;
  }

  :deep(.n-form-item-feedback-wrapper) {
    // min-height: 10px;
    // height: 10px;
  }
}
</style>
